package com.zzk.jpmvvmbase.base

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.LogUtils
import com.zzk.jpmvvmbase.ext.getVmClazz
import java.lang.reflect.ParameterizedType

/**
 *  * 公共基础类，自动把ViewModel注入Fragment和Databind注入进来了
 *
 * @ProjectName:    JetPackMVVMBase
 * @Package:        com.zzk.jpmvvmbase.base
 * @ClassName:      BaseFragment
 * @Description:
 * @Author:         brilliantzhao
 * @CreateDate:     2021.1.19 14:15
 * @UpdateUser:
 * @UpdateDate:     2021.1.19 14:15
 * @UpdateRemark:
 * @Version:        1.0.0
 */
abstract class BaseFragment<VM : BaseViewModel, DB : ViewDataBinding> : Fragment(), IBaseView {

    //##########################  custom variables start ##########################################

    private var TAG = javaClass.simpleName

    //该类绑定的ViewDataBinding
    lateinit var mDatabind: DB
    lateinit var mViewModel: VM
    lateinit var mActivity: AppCompatActivity

    //##########################  custom variables end  ###########################################

    //##########################  override custom metohds start ###################################

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.d(TAG, "onAttach")
        mActivity = context as AppCompatActivity
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate")
        initParam()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Log.d(TAG, "onCreateView")
        val cls =
            (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[1] as Class<*>
        if (ViewDataBinding::class.java != cls && ViewDataBinding::class.java.isAssignableFrom(cls)) {
            mDatabind = DataBindingUtil.inflate(
                inflater,
                initContentView(inflater, container, savedInstanceState),
                container,
                false
            )
            return mDatabind?.root
        }
        return inflater.inflate(
            initContentView(inflater, container, savedInstanceState),
            container,
            false
        )
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.d(TAG, "onViewCreated")
        //私有的初始化Databinding和ViewModel方法
        initViewDataBinding()
        //私有的ViewModel与View的契约事件回调逻辑
        registorDefUIChange()
        //
        initData(savedInstanceState)
        //页面事件监听的方法，一般用于ViewModel层转到View层的事件注册
        initViewObservable()
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        Log.d(TAG, "onActivityCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d(TAG, "onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.d(TAG, "onDetach")
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        Log.d(TAG, "onHiddenChanged:hidden->$hidden")
    }

    //##########################  override custom metohds end  ####################################

    //##########################  override third methods start ####################################

    override fun initParam() {
    }

    override fun initData(savedInstanceState: Bundle?) {
    }

    override fun initViewObservable() {
    }

    /**
     * 初始化根布局
     *
     * @return 布局layout的id
     */
    abstract fun initContentView(
        inflater: LayoutInflater?,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): Int

    /**
     * 抽象方法，方便在子类中自定义样式
     */
    abstract fun showLoadingDialog(message: String = "请求网络中...")

    abstract fun dismissLoadingDialog()

    //##########################  override third methods end  #####################################

    //##########################  custom metohds start     ########################################

    /**
     * 跳转页面
     *
     * @param clz 所跳转的目的Activity类
     */
    open fun startActivity(clz: Class<*>?) {
        startActivity(Intent(context, clz))
    }

    /**
     * 跳转页面
     *
     * @param clz    所跳转的目的Activity类
     * @param bundle 跳转所携带的信息
     */
    open fun startActivity(clz: Class<*>?, bundle: Bundle?) {
        val intent = Intent(context, clz)
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        startActivity(intent)
    }

    private fun initViewDataBinding() {
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType) {
            val tp = type.actualTypeArguments[0]
            val tClass = tp as? Class<VM> ?: BaseViewModel::class.java
            mViewModel = ViewModelProvider(this).get(tClass) as VM
        }
        //支持LiveData绑定xml，数据改变，UI自动会更新
        mDatabind.lifecycleOwner = this
        //
        lifecycle.addObserver(mViewModel)
    }

    /**
     * 注册 UI 事件
     */
    private fun registorDefUIChange() {
        mViewModel.loadingChange.showDialog.observeInFragment(this, Observer {
            showLoadingDialog(it)
        })
        mViewModel.loadingChange.dismissDialog.observeInFragment(this, Observer {
            dismissLoadingDialog()
        })
    }

    /**
     * 将非该Fragment绑定的ViewModel添加 loading回调 防止出现请求时不显示 loading 弹窗bug
     * @param viewModels Array<out BaseViewModel>
     */
    protected fun addLoadingObserve(vararg viewModels: BaseViewModel) {
        viewModels.forEach { viewModel ->
            //显示弹窗
            viewModel.loadingChange.showDialog.observeInFragment(this, Observer {
                showLoadingDialog(it)
            })
            //关闭弹窗
            viewModel.loadingChange.dismissDialog.observeInFragment(this, Observer {
                dismissLoadingDialog()
            })
        }
    }

    //##########################  custom metohds end   ############################################

}